//
// Created by v on 24-8-7.
//

#include "iot_connect_tuya.h"
#include "tuyalink_core.h"
#include "tuya_log.h"
#include "tuya_error_code.h"
#include "tuya_cacert.h"
#include "esp_log.h"
#include "sys/time.h"

#define TUYA_PRODUCT_KEY CONFIG_ESP_TUYA_PRODUCT_KEY
#define TUYA_DEVICE_UUID CONFIG_ESP_TUYA_DEVICE_UUID
#define TUYA_DEVICE_AUTHKEY CONFIG_ESP_TUYA_DEVICE_AUTHKEY


typedef struct
{
    tuya_mqtt_context_t client_instance;
    tuya_mqtt_context_t* context;
    int inited;
    int connected;
} IoTConnectHandler;

static IoTConnectHandler s_connectHandler;

void on_connected(tuya_mqtt_context_t* context, void* user_data)
{
    TY_LOGI("on connected");
    s_connectHandler.context = context;
    s_connectHandler.connected = 1;

    /* data model test code */
//    tuyalink_thing_data_model_get(context, NULL);
//    tuyalink_thing_desired_get(context, NULL, "[\"power\"]");
//    tuyalink_thing_property_report(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
//    tuyalink_thing_property_report_with_ack(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
//    tuyalink_thing_event_trigger(context, NULL, "{\"eventCode\":\"boom\",\"eventTime\":1626197189630,\"outputParams\":{\"param1\":100}}");
//    tuyalink_thing_batch_report(context, "{\"msgId\":\"45lkj3551234001\",\"time\":1626197189638,\"sys\":{\"ack\":1},\"data\":{\"properties\":{\"power\":{\"value\":11,\"time\":1626197189638}},\"events\":{\"boom\":{\"outputParams\":{\"param1\":\"10\"},\"eventTime\":1626197189001}}}}");
}

void on_disconnect(tuya_mqtt_context_t* context, void* user_data)
{
    s_connectHandler.connected = 0;
    TY_LOGI("on disconnect");
}

void on_messages(tuya_mqtt_context_t* context, void* user_data, const tuyalink_message_t* msg)
{
    TY_LOGI("on message id:%s, type:%d, code:%d", msg->msgid, msg->type, msg->code);
    switch (msg->type) {
        case THING_TYPE_MODEL_RSP:
            TY_LOGI("Model data:%s", msg->data_string);
            break;

        case THING_TYPE_PROPERTY_SET:
            TY_LOGI("property set:%s", msg->data_string);
            break;

        case THING_TYPE_PROPERTY_REPORT_RSP:
            break;

        default:
            break;
    }
    printf("\r\n");
}


int iot_connect_init()
{
    int ret = OPRT_OK;
    if (s_connectHandler.inited)
    {
        return 0;
    }

    ret = tuya_mqtt_init(&s_connectHandler.client_instance, &(const tuya_mqtt_config_t) {
            .host = "m2.tuyacn.com",
            .port = 8883,
            .cacert = (uint8_t*)tuya_cacert_pem,
            .cacert_len = sizeof(tuya_cacert_pem),
            .device_id = TUYA_DEVICE_UUID,
            .device_secret = TUYA_DEVICE_AUTHKEY,
            .keepalive = 60,
            .timeout_ms = 2000,
            .on_connected = on_connected,
            .on_disconnect = on_disconnect,
            .on_messages = on_messages
    });
    assert(ret == OPRT_OK);

    ret = tuya_mqtt_connect(&s_connectHandler.client_instance);
    assert(ret == OPRT_OK);
    s_connectHandler.inited = true;

    return 0;
}

int iot_connect_do_block()
{
    if (!s_connectHandler.inited)
    {
        return -2;
    }
    for(;;) {
        /* Loop to receive packets, and handles client keepalive */
        tuya_mqtt_loop(&s_connectHandler.client_instance);
    }
    return -1;
}

int iot_connect_deinit()
{
    if (s_connectHandler.inited == 0)
    {
        return 0;
    }
    tuya_mqtt_disconnect(&s_connectHandler.client_instance);
    tuya_mqtt_deinit(&s_connectHandler.client_instance);
    s_connectHandler.inited = 0;
    return 0;
}

int iot_connect_is_connected()
{
    return s_connectHandler.connected;
}

int iot_connect_report_property(char *data, unsigned int len)
{
    int ret = tuyalink_thing_property_report_with_ack(s_connectHandler.context, TUYA_DEVICE_UUID, data);
    if (ret < 0)
    {
        ESP_LOGE("iot", "property send failed [%d]\n", ret);
        return ret;
    }
    return 0;
}

unsigned long long get_time_ms()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (unsigned long long)tv.tv_sec * 1000 + (unsigned long long) tv.tv_usec /1000;
}

int iot_connect_report_ridar_status(int value)
{
    char st_data[80] = {0};

    unsigned long long ms = get_time_ms();
    snprintf(st_data, sizeof(st_data), "{\"is_human_exist\":{\"value\":%d,\"time\":%llu}}",
             value, ms);
    ESP_LOGI("iot", "ridar status: [%s]\n", st_data);
    return iot_connect_report_property(st_data, strlen(st_data));
}
